package fileReader.demo.reader;

import java.awt.geom.Point2D;
import java.io.DataInputStream;
import java.io.IOException;

public class PolygonReader extends LayerReader {

	/**
	 * Method reads depth area specific data from main file (.shp)
	 * For more information read ESRI Technical Dscription 
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param fileLength length of file to read
	 * @author Mari
	 */
	public void readPolygonData(DataInputStream dataIn, String layer, MapLayer mapLayer, int fileLength) {
		
		try {
			int i = 100;									// mainheader is already read
			while(i<fileLength)
			{
				i = i + 8;
				
				dataIn.readInt();						//rec header
				int contLength = 2*(dataIn.readInt());	//rec header
				readLittleInteger(dataIn.readInt());	//shapetype	
	
				Box bb = makeBoundingBox(dataIn);
	
				int numOfParts = readLittleInteger(dataIn.readInt());	//number of parts
				int numOfPoints = readLittleInteger(dataIn.readInt());	//number of points
				
				dataIn.skipBytes(numOfParts*4);							//skip some pointers
				
				if(layer.contentEquals("deptharea")){
					createDepthArea(dataIn, numOfParts, numOfPoints, mapLayer, bb);
				}
				else if(layer.contentEquals("building")){
					createBuilding(dataIn, numOfParts, numOfPoints, mapLayer, bb);
				}
				else if(layer.contentEquals("generarea")){
					createGenerArea(dataIn, numOfParts, numOfPoints, mapLayer, bb);
				}
				else if(layer.contentEquals("fwayarea")){
					createFWay(dataIn, numOfParts, numOfPoints, mapLayer, bb);
				}	
				else if(layer.contentEquals("builtupare")){
					createBuiltupare(dataIn, numOfParts, numOfPoints, mapLayer, bb);
				}
				
				i = i + contLength;
			}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + layer);
			e.printStackTrace();
		}
		
	}

	private void createDepthArea(DataInputStream dataIn, int numOfParts, int numOfPoints, MapLayer mapLayer, Box bb) {
		PolygonDrawer motherPolygon = null;
		int n = 0;
		int m = 0;
		try{
		while((n < numOfParts) && (m < numOfPoints))
		{
			PolygonDrawer polygon = new DepthArea();
			if(n==0)
			{
				motherPolygon = polygon; 
			}
			polygon.setBoundingBox(bb);
			MapLayer.setGlobalBoundingBox(bb);
			
			double x = readLittleDouble(dataIn.readDouble());
			double y = readLittleDouble(dataIn.readDouble());
	
			Point2D vertex = new Point2D.Double(x,y);
			Point2D firstver = new Point2D.Double(x,y);
	
			//vertex = new Point2D.Double(x,y);
			//firstver = new Point2D.Double(x,y);
			
			polygon.getVertexList().add(vertex);	
			m++;
			
			//while vertex is not the same as first vertex
			//it belongs to the same polygon
			do
			{
				//x = readLittleDouble(dataIn.readDouble());
				//y = readLittleDouble(dataIn.readDouble());
	
				vertex = makeVertex(dataIn);
	
				polygon.getVertexList().add(vertex);
				m++;		
			}while(firstver.getX()!=vertex.getX() || firstver.getY()!=vertex.getY());
			
			//if this is not a mother polygon we have hole == more than 1 part
			//let's add it into hole list
			if(n>0)
			{
				motherPolygon.getHoleList().add(polygon);
			}
			//first part is the mother polygon, let's add it into data vector
			else
			{
				mapLayer.data.add(polygon);
			}
			n++;
		}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}
	
	private void createBuilding(DataInputStream dataIn, int numOfParts, int numOfPoints, MapLayer mapLayer, Box bb) {
		int n = 0;
		int m = 0;
		try{
			while((n < numOfParts) && (m < numOfPoints))
			{
				PolygonDrawer building = new PolygonDrawer();
				building.setBoundingBox(bb);
				
				double x = readLittleDouble(dataIn.readDouble());
				double y = readLittleDouble(dataIn.readDouble());

				Point2D vertex = new Point2D.Double(x,y);
				Point2D firstver = new Point2D.Double(x,y);

				//vertex = new Point2D.Double(x,y);
				//firstver = new Point2D.Double(x,y);
				
				building.getVertexList().add(vertex);	
				m++;
				
				do
				{
					//x = readLittleDouble(dataIn.readDouble());
					//y = readLittleDouble(dataIn.readDouble());

					vertex = makeVertex(dataIn);

					building.getVertexList().add(vertex);
					m++;		
				}while(firstver.getX()!= vertex.getX() || firstver.getY()!= vertex.getY());
				
				mapLayer.data.add(building);
				
				n++;
			}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}

	private void createGenerArea(DataInputStream dataIn, int numOfParts, int numOfPoints, MapLayer mapLayer, Box bb) {
		int n = 0;
		int m = 0;
		try{
			while((n < numOfParts) && (m < numOfPoints))
			{
				PolygonDrawer generarea = new PolygonDrawer();
				generarea.setBoundingBox(bb);
				
				double x = readLittleDouble(dataIn.readDouble());
				double y = readLittleDouble(dataIn.readDouble());
	
				Point2D vertex = new Point2D.Double(x,y);
				Point2D firstver = new Point2D.Double(x,y);
	
				//vertex = new Point2D.Double(x,y);
				//firstver = new Point2D.Double(x,y);
				
				generarea.getVertexList().add(vertex);	
				m++;
				
				do
				{
					//x = readLittleDouble(dataIn.readDouble());
					//y = readLittleDouble(dataIn.readDouble());
	
					vertex = makeVertex(dataIn);
	
					generarea.getVertexList().add(vertex);
					m++;		
				}while(firstver.getX()!= vertex.getX() || firstver.getY()!= vertex.getY());
				
				mapLayer.data.add(generarea);
				
				n++;
			}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}
	
	private void createFWay(DataInputStream dataIn, int numOfParts, int numOfPoints, MapLayer mapLayer, Box bb) {
		int n = 0;
		int m = 0;
		try{
			while((n < numOfParts) && (m < numOfPoints))
			{
				PolygonDrawer fwayarea = new PolygonDrawer();
				fwayarea.setBoundingBox(bb);
				
				double x = readLittleDouble(dataIn.readDouble());
				double y = readLittleDouble(dataIn.readDouble());
	
				Point2D vertex = new Point2D.Double(x,y);
				Point2D firstver = new Point2D.Double(x,y);
	
				//vertex = new Point2D.Double(x,y);
				//firstver = new Point2D.Double(x,y);
				
				fwayarea.getVertexList().add(vertex);	
				m++;
				
				do
				{
					//x = readLittleDouble(dataIn.readDouble());
					//y = readLittleDouble(dataIn.readDouble());
	
					vertex = makeVertex(dataIn);
	
					fwayarea.getVertexList().add(vertex);
					m++;		
				}while(firstver.getX()!= vertex.getX() || firstver.getY()!= vertex.getY());
				
				mapLayer.data.add(fwayarea);
				
				n++;
			}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}
	
	private void createBuiltupare(DataInputStream dataIn, int numOfParts, int numOfPoints, MapLayer mapLayer, Box bb) {
		int n = 0;
		int m = 0;
		try{
			while((n < numOfParts) && (m < numOfPoints))
			{
				PolygonDrawer builtupare = new PolygonDrawer();
				builtupare.setBoundingBox(bb);
				
				double x = readLittleDouble(dataIn.readDouble());
				double y = readLittleDouble(dataIn.readDouble());
	
				Point2D vertex = new Point2D.Double(x,y);
				Point2D firstver = new Point2D.Double(x,y);
				
				builtupare.getVertexList().add(vertex);	
				m++;
				
				do
				{	
					vertex = makeVertex(dataIn);
	
					builtupare.getVertexList().add(vertex);
					m++;		
				}while(firstver.getX()!=vertex.getX() || firstver.getY()!= vertex.getY());
				 
				mapLayer.data.add(builtupare);
				
				n++;
			}
		} 
		catch (IOException e) 
		{
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}
	
	/**
	 * Method reads depth area specific data from database file (.dbf)
	 * For more information read dBase Language Reference 111902 and ESRI Study Report
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param numOfRecords number of records to read from a file
	 * @author Mari
	 */
	public void readDepthAreaAttributes(DataInputStream dataIn, PolygonMapLayer mapLayer, int numOfRecords) {
		try{
			for(int n=0; n<numOfRecords; n++)
			{
				char value = (char)dataIn.readByte(); //record deleted flag
				if(value == 42)
				{
					recordDeleted();
				}	
				skipLayerBytes(dataIn);
				
				String minDepthString = "";
				for(int m=0; m<6; m++)	// MINDEPTH
				{
					minDepthString = minDepthString + (char)dataIn.readByte();	
				}
				double minDepth = Double.parseDouble(minDepthString);
				((DepthArea) mapLayer.data.get(n)).setMinDepth(minDepth);
				
				dataIn.skipBytes(6);	// HGHTLAKE
				
				dataIn.skipBytes(11);	// TYPEDEPR
				
				String maxDepthString = "";
				for(int m=0; m<6; m++)	// MAXDEPTH
				{
					maxDepthString = maxDepthString + (char)dataIn.readByte();	
				}
				double maxDepth = Double.parseDouble(maxDepthString);
				((DepthArea) mapLayer.data.get(n)).setMaxDepth(maxDepth);
				
			}
		}catch (IOException e) {
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}

	/**
	 * Method reads building specific data from database file (.dbf)
	 * For more information read dBase Language Reference 111902 and ESRI Study Report
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param numOfRecords number of records to read from a file
	 * @author Mari
	 */
	public void readBuildingAttributes(DataInputStream dataIn, PolygonMapLayer mapLayer, int numOfRecords) {
		try{
		for(int n=0; n<numOfRecords; n++)
		{
			char value = (char)dataIn.readByte(); //record deleted flag
			if(value == 42)
			{
				recordDeleted();
			}	
			
			skipLayerBytes(dataIn);
			
			dataIn.skipBytes(32);	// INT_NAME
			
			dataIn.skipBytes(11);	// STATUSCNST
			
			dataIn.skipBytes(6);	// VERLEN
			
			dataIn.skipBytes(7);	// HGHTBLDING
			
			dataIn.skipBytes(11);	// USEBLDING
			
			dataIn.skipBytes(32);	// NAMEBLDING
	
		}
		}catch (IOException e) {
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}


	/**
	 * Method reads gener area specific data from database file (.dbf)
	 * For more information read dBase Language Reference 111902 and ESRI Study Report
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param numOfRecords number of records to read from a file
	 * @author Mari
	 */
	public void readGenerAreaAttributes(DataInputStream dataIn, PolygonMapLayer mapLayer, int numOfRecords) {
		try{
		for(int n=0; n<numOfRecords; n++)
		{
			char value = (char)dataIn.readByte(); //record deleted flag
			if(value == 42)
			{
				recordDeleted();
			}	
			skipLayerBytes(dataIn);
			
			dataIn.skipBytes(11);	// TYPEDEPR
	
		}
		}catch (IOException e) {
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}


	/**
	 * Method reads fway specific data from database file (.dbf)
	 * For more information read dBase Language Reference 111902 and ESRI Study Report
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param numOfRecords number of records to read from a file
	 * @author Mari
	 */
	public void readFwayAttributes(DataInputStream dataIn, PolygonMapLayer mapLayer, int numOfRecords) {
		try{
		for(int n=0; n<numOfRecords; n++)
		{
			char value = (char)dataIn.readByte(); //record deleted flag
			if(value == 42)
			{
				recordDeleted();
			}	
			skipLayerBytes(dataIn);
			
			dataIn.skipBytes(11);	// NUMFRWYARE
			
			dataIn.skipBytes(17);	// CANALOID
			
			dataIn.skipBytes(32);	// INT_NAME
			
			dataIn.skipBytes(4);	// MDRGFWYARE
			
			dataIn.skipBytes(11);	// TRAFFICFLO
			
			dataIn.skipBytes(11);	// FI_STFWYAR
	
			dataIn.skipBytes(11);	// TYPEFWYARE
			
			dataIn.skipBytes(4);	// SDEPFWYARE
			
			dataIn.skipBytes(64);	// NAMEFWYARE
	
			dataIn.skipBytes(11);	// TYPETSSARE
			
			dataIn.skipBytes(6);	// ORIENT
			
			dataIn.skipBytes(11);	// CATTSSAREA
			
		}
		}catch (IOException e) {
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}


	/**
	 * Method reads builtupare specific data from database file (.dbf)
	 * For more information read dBase Language Reference 111902 and ESRI Study Report
	 * 
	 * @param dataIn data input stream for reading a file
	 * @param layer map layer in which data is stored
	 * @param numOfRecords number of records to read from a file
	 * @author Mari
	 */
	public void readBuiltupareAttributes(DataInputStream dataIn, PolygonMapLayer mapLayer, int numOfRecords) {
		try{
		for(int n=0; n<numOfRecords; n++)
		{
			char value = (char)dataIn.readByte(); //record deleted flag
			if(value == 42)
			{
				recordDeleted();
			}	
			
			skipLayerBytes(dataIn);
			
			dataIn.skipBytes(32);	// INT_NAME
			
			dataIn.skipBytes(11);	// TYPEBUAARE
			
			dataIn.skipBytes(32);	// NAMEBUAARE
			
		}
		}catch (IOException e) {
			readDataError();
			System.out.println("polygonreader" + mapLayer);
			e.printStackTrace();
		}
	}
	
}
